/****

    activequant - activestocks.eu

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

	
	contact  : contact@activestocks.eu
    homepage : http://www.activestocks.eu

****/
package org.activequant.container;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;


/**
 * An ITradeSystemContainer implementation. Holds the following associated variables:
 * <ul>
 * <li>systemsFolder(String)</li>
 * <li>systemsContexts(List&lt;ITradeSystemContext&gt;)</li>
 * <li>systemLoaders(ITradeSystemFactory[])</li>
 * <li>isRunning(boolean)</li>
 * </ul>
 * <br>
 * <b>History:</b><br>
 *  - [11.05.2007] Created (Erik Nijkamp)<br>
 *
 *  @author Erik Nijkamp
 */
public class SimpleJarContainer implements ITradeSystemContainer {
	
	private final static Logger log = Logger.getLogger(SimpleJarContainer.class);
	/**
	 * private static final String DEFAULT_SYSTEMS_FOLDER = "systems";
	 */
	private static final String DEFAULT_SYSTEMS_FOLDER = "systems";
	/**
	 * private String systemsFolder = DEFAULT_SYSTEMS_FOLDER;
	 */
	private String systemsFolder = DEFAULT_SYSTEMS_FOLDER;
	/**
	 * private List&lt;ITradeSystemContext&gt; systemsContexts = new ArrayList&lt;ITradeSystemContext&gt;();
	 */
	private List<ITradeSystemContext> systemsContexts = new ArrayList<ITradeSystemContext>();
	/**
	 * private ITradeSystemFactory[] systemLoaders = { };
	 */
	private ITradeSystemFactory[] systemLoaders = { /* new SpringContextFactory() */ };
	/**
	 * private boolean isRunning = false;
	 */
	private boolean isRunning = false;
	/**
	 * an empty SimpleJarContainer(ITradeSystemContainer implementation) constructor
	 */
	public SimpleJarContainer() {
		
	}
	/**
	 * constructs a SimpleJarContainer(ITradeSystemContainer implementation) using the given systemsFolder(String) to set its associated systemsFolder(String)
	 * @param systemsFolder
	 */
	public SimpleJarContainer(String systemsFolder) {
		this.systemsFolder = systemsFolder;
	}
	/**
	 * loops through the ".jar" files found in the "./${systemsFolder}" folder, loads and starts an ITradeSystemContext from each of them and adds them to the
	 * associated systemsContexts(List&lt;ITradeSystemContext&gt;).<br/>
	 * Then it sets the associated isRunning(boolean) to true
	 */
	public void start() throws Exception {
		log.info("Starting " + this.getClass().getSimpleName());
		Map<String, File> systems = getTradeSystems();
		for(File file: systems.values()) {
			ITradeSystemContext context = loadTradeSystem(file);
			systemsContexts.add(context);
			context.start();
		}
		isRunning = true;
	}
	/**
	 * sets the associated isRunning(boolean) to false
	 */
	public void stop() {
		isRunning = false;
	}	
	/**
	 * returns the associated isRunning(boolean)
	 */
	public boolean isRunning() {
		return isRunning;
	}
	/**
	 * loops through the associated systemLoaders(ITradeSystemFactory[]) looking for one that supports the given file(File). Once it finds one,
	 * it invokes <code>loader.loadContext(tradesystem)</code> and returns the resulting ITradeSystemContext
	 * @param file
	 * @return
	 * @throws Exception
	 */
	private ITradeSystemContext loadTradeSystem(File file) throws Exception {
		for(ITradeSystemFactory loader: systemLoaders) {
			if(loader.isSupported(file)) {
				return loader.loadContext(file);
			}
		}
		throw new Exception("No loader found for jar '"+file+"'.");
	}
	/**
	 * returns a Map&lt;String,File&gt; holding the name-file pairs of the .jar files found in the "./${systemsFolder}" folder
	 * @return
	 * @throws Exception
	 */
	private Map<String, File> getTradeSystems() throws Exception {
		File folder = new File(getRootPath() + "/" + systemsFolder);
		if (!folder.exists())
			throw new FileNotFoundException(folder.getAbsolutePath());
		return getJarsFromFolder(folder);
	}
	/**
	 * returns a Map&lt;String,File&gt; holding the name-file pairs of the .jar files found in the given folder(File)
	 * @param folder
	 * @return
	 * @throws Exception
	 */
	private Map<String, File> getJarsFromFolder(File folder) throws Exception {
		Map<String, File> systems = new HashMap<String, File>();
		for (File file: folder.listFiles()) {
			if (file.isFile() && file.getName().endsWith(".jar")) {
				String name = file.getName().substring(0,
						file.getName().length() - 4);
				log.info("Tradesystem found '" + name + "'.");
				systems.put(name, file);
			}
		}
		return systems;
	}
	/**
	 * returns the canonical path of the current folder (".")
	 * @return
	 * @throws Exception
	 */
	public String getRootPath() throws Exception {
		// TODO switch resolving between j2ee and standard java app
		/*URL reference = getClass().getClassLoader().getResource(systemsFile);
		log.info(new File(reference.getPath()).getParentFile().getParentFile()
				.getParent());
		return new File(reference.toURI()).getParentFile().getParentFile()
				.getParent();*/
		return new File(".").getCanonicalPath();
	}
}
